#!/usr/bin/env node
import { execSync } from "node:child_process";
import fs from "node:fs";
import { writeFile } from "node:fs/promises";
import path from "node:path";
import pLimit from "p-limit";

// 获取目标文件夹路径，默认为程序运行目录
const targetDir = process.argv[2] ? path.resolve(process.argv[2]) : process.cwd();

execSync("pnpm list --json --depth=Infinity > tmp.json", { stdio: "inherit" });

const jsonFile = path.resolve(targetDir, "tmp.json");
const tarballDir = path.resolve(targetDir, "tarballs");

if (!fs.existsSync(jsonFile)) {
  console.error("tmp.json 文件不存在");
  process.exit(1);
}

const content = fs.readFileSync(jsonFile, "utf8");
const data = JSON.parse(content);

const pkgMap = new Map();

function ensureDirExists(dir) {
  if (!fs.existsSync(dir)) {
    fs.mkdirSync(dir, { recursive: true });
  }
}

function collectDeps(obj) {
  if (!obj)
    return;
  for (const depType of ["dependencies", "devDependencies"]) {
    const deps = obj[depType];
    if (deps) {
      for (const [name, info] of Object.entries(deps)) {
        if (info && info.version && info.path) {
          const key = `${name}@@${info.version}`;
          const url = info.resolved;
          if (!pkgMap.has(key)) {
            pkgMap.set(key, url);
            // 递归收集子依赖
            collectDeps(info);
          }
        }
      }
    }
  }
}

for (const root of data) {
  collectDeps(root);
}

if (!fs.existsSync(tarballDir)) {
  fs.mkdirSync(tarballDir);
}

async function main() {
  const limit = pLimit(5); // 并发数限制为 5
  const tasks = [];
  const time = Date.now();
  for (const key of pkgMap.keys()) {
    const url = pkgMap.get(key);
    const [name, version] = key.split("@@");
    console.log(`打包: ${`${name}_${version}`} 路径: ${url}`);

    tasks.push(limit(async () => {
      const out = path.join(tarballDir, `${`${name}_${version}`}.tgz`);
      // 确保输出目录存在
      ensureDirExists(path.dirname(out));
      // 使用 fetch 下载 tgz
      await fetch(url)
        .then(res => res.arrayBuffer())
        .then((buffer) => {
          return writeFile(out, Buffer.from(buffer));
        })
        .catch((err) => {
          console.error(`打包失败: ${name} - ${err.message}`);
        });
    }));
  }
  await Promise.all(tasks);
  console.log("全部打包完成：", tasks.length);
  console.log(`耗时: ${(Date.now() - time) / 1000} 秒`);

  // 删除临时文件
  fs.unlinkSync(jsonFile);
  console.log("临时文件 tmp.json 已删除");
}

main();
